/**
 * @file soem_master.c
 * @brief SOEM EtherCAT主站实现
 * 
 * 该文件实现了基于SOEM EtherCAT主站的接口
 */

#include "ethercat_interface.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 包含SOEM EtherCAT主站头文件 */
#include "../soem/ethercat.h"

/* 定义SOEM主站相关数据结构 */
typedef struct {
    EtherCATInterface interface;  /* 必须放在第一位，用于类型转换 */
    
    /* SOEM特有数据 */
    char io_map[4096];
    int expected_wkc;
    int slave_count;
    bool in_op;
} SOEMMaster;

/* SOEM接口实现函数 */
static bool soem_init(const char *ifname) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.init));
    
    /* 初始化SOEM，绑定套接字到网络接口 */
    if (!ec_init(ifname)) {
        fprintf(stderr, "Failed to initialize SOEM on %s\n", ifname);
        return false;
    }
    
    return true;
}

static int soem_config_init(void) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.config_init));
    
    /* 查找并自动配置从站 */
    int slave_count = ec_config_init(FALSE);
    if (slave_count <= 0) {
        fprintf(stderr, "No slaves found!\n");
        return 0;
    }
    
    soem->slave_count = slave_count;
    printf("%d slaves found and configured.\n", slave_count);
    
    return slave_count;
}

static bool soem_config_map(void *io_map) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.config_map));
    
    /* 配置过程数据映射 */
    if (io_map) {
        ec_config_map(io_map);
    } else {
        ec_config_map(soem->io_map);
    }
    
    /* 计算预期的工作计数器值 */
    soem->expected_wkc = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
    
    return true;
}

static bool soem_config_dc(void) {
    /* 配置分布式时钟 */
    ec_configdc();
    return true;
}

static bool soem_state_check(uint16_t slave, EtherCATState state, int timeout) {
    /* 转换状态枚举 */
    uint16_t ec_state;
    switch (state) {
        case EC_STATE_INIT: ec_state = EC_STATE_INIT; break;
        case EC_STATE_PREOP: ec_state = EC_STATE_PRE_OP; break;
        case EC_STATE_SAFEOP: ec_state = EC_STATE_SAFE_OP; break;
        case EC_STATE_OPERATIONAL: ec_state = EC_STATE_OPERATIONAL; break;
        default: return false;
    }
    
    /* 检查状态 */
    return ec_statecheck(slave, ec_state, timeout) == ec_state;
}

static bool soem_write_state(uint16_t slave, EtherCATState state) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.write_state));
    
    /* 转换状态枚举 */
    uint16_t ec_state;
    switch (state) {
        case EC_STATE_INIT: ec_state = EC_STATE_INIT; break;
        case EC_STATE_PREOP: ec_state = EC_STATE_PRE_OP; break;
        case EC_STATE_SAFEOP: ec_state = EC_STATE_SAFE_OP; break;
        case EC_STATE_OPERATIONAL: ec_state = EC_STATE_OPERATIONAL; break;
        default: return false;
    }
    
    /* 设置从站状态 */
    ec_slave[slave].state = ec_state;
    ec_writestate(slave);
    
    /* 如果设置为操作状态，更新内部标志 */
    if (slave == 0 && state == EC_STATE_OPERATIONAL) {
        soem->in_op = true;
    } else if (slave == 0 && state == EC_STATE_INIT) {
        soem->in_op = false;
    }
    
    return true;
}

static bool soem_send_processdata(void) {
    ec_send_processdata();
    return true;
}

static int soem_receive_processdata(int timeout) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.receive_processdata));
    
    int wkc = ec_receive_processdata(timeout);
    return wkc;
}

static bool soem_read_state(void) {
    ec_readstate();
    return true;
}

static void soem_close(void) {
    /* 关闭SOEM，释放套接字 */
    ec_close();
}

static int soem_get_slave_count(void) {
    SOEMMaster *soem = (SOEMMaster *)((EtherCATInterface *)__func__ - offsetof(SOEMMaster, interface.get_slave_count));
    return soem->slave_count;
}

static uint8_t* soem_get_slave_inputs(uint16_t slave) {
    if (slave > 0 && slave <= ec_slavecount) {
        return ec_slave[slave].inputs;
    }
    return NULL;
}

static uint8_t* soem_get_slave_outputs(uint16_t slave) {
    if (slave > 0 && slave <= ec_slavecount) {
        return ec_slave[slave].outputs;
    }
    return NULL;
}

/* 创建SOEM主站实例 */
EtherCATInterface* create_soem_master(void) {
    SOEMMaster *soem = (SOEMMaster *)malloc(sizeof(SOEMMaster));
    if (!soem) {
        return NULL;
    }
    
    memset(soem, 0, sizeof(SOEMMaster));
    
    /* 初始化接口函数 */
    soem->interface.init = soem_init;
    soem->interface.config_init = soem_config_init;
    soem->interface.config_map = soem_config_map;
    soem->interface.config_dc = soem_config_dc;
    soem->interface.state_check = soem_state_check;
    soem->interface.write_state = soem_write_state;
    soem->interface.send_processdata = soem_send_processdata;
    soem->interface.receive_processdata = soem_receive_processdata;
    soem->interface.read_state = soem_read_state;
    soem->interface.close = soem_close;
    soem->interface.get_slave_count = soem_get_slave_count;
    soem->interface.get_slave_inputs = soem_get_slave_inputs;
    soem->interface.get_slave_outputs = soem_get_slave_outputs;
    
    return &soem->interface;
}

/* 销毁SOEM主站实例 */
void destroy_soem_master(EtherCATInterface *interface) {
    if (interface) {
        SOEMMaster *soem = (SOEMMaster *)interface;
        soem->interface.close();
        free(soem);
    }
}